#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>

typedef struct Node
{
    int val;
    struct Node* next;
}Node;

typedef struct
{
    Node* front;
    Node* rear;
    int k;
} MyCircularQueue;

MyCircularQueue* myCircularQueueCreate(int k)
{
    assert(k >= 0);
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    obj->k = k;
    obj->front = NULL;
    obj->rear = NULL;

    Node* cur = NULL;
    while (k--)
    {
        Node* node = (Node*)malloc(sizeof(Node));

        if (obj->front == NULL)
        {
            obj->front = node;
            cur = node;
        }
        else
        {
            cur->next = node;
            cur = node;
        }
    }
    cur->next = obj->front;

    return obj;
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{
    return obj->rear == NULL;
}

bool myCircularQueueIsFull(MyCircularQueue* obj)
{
    if (obj->rear == NULL)
        return false;
    return obj->rear->next == obj->front;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{
    if (myCircularQueueIsFull(obj))
    {
        return false;
    }

    if (obj->rear == NULL)
    {
        obj->rear = obj->front;
        obj->rear->val = value;
    }
    else
    {
        obj->rear = obj->rear->next;
        obj->rear->val = value;
    }
    return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj)
{
    if (myCircularQueueIsEmpty(obj))
    {
        return false;
    }

    if (obj->front == obj->rear)
    {
        obj->rear = NULL;
    }
    else
    {
        obj->front = obj->front->next;
    }
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj)
{
    if (myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    return obj->front->val;
}

int myCircularQueueRear(MyCircularQueue* obj)
{
    if (myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    return obj->rear->val;
}



void myCircularQueueFree(MyCircularQueue* obj)
{
    Node* cur = obj->front;

    while (cur != obj->front)
    {
        Node* next = cur -> next;
        free(cur);
        cur = next;
    }

    free(obj);
}

int main()
{
    MyCircularQueue* cque = myCircularQueueCreate(3);
    bool ret = myCircularQueueEnQueue(cque, 1);
    ret = myCircularQueueEnQueue(cque, 2);
    ret = myCircularQueueEnQueue(cque, 3);
    ret = myCircularQueueEnQueue(cque, 4);

    int x = myCircularQueueRear(cque);
    return 0;
}